package cn.jbolt.core.service;

import cn.jbolt.core.base.JBoltMsg;
import cn.jbolt.core.bean.JBoltAppLinkTarget;
import cn.jbolt.core.common.enums.JBoltApplicationType;
import cn.jbolt.core.common.enums.JBoltSystemLogTargetType;
import cn.jbolt.core.enumutil.JBoltEnum;
import cn.jbolt.core.kit.JBoltUserKit;
import cn.jbolt.core.model.Application;
import cn.jbolt.core.model.User;
import cn.jbolt.core.service.base.JBoltBaseService;
import cn.jbolt.core.util.JBoltMethodCaller;
import cn.jbolt.core.util.JBoltRandomUtil;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Base64Kit;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Okv;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;

import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Application Service
 *
 * @ClassName: ApplicationService
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2020年5月2日
 */
public class JBoltApplicationService extends JBoltBaseService<Application> {
    protected Application dao = new Application().dao();
    @Inject
    protected JBoltUserService jboltUserService;

    @Override
    protected Application dao() {
        return dao;
    }


    /**
     * 后台管理分页查询
     *
     * @param pageNumber
     * @param pageSize
     * @param keywords
     * @param type
     * @param enable
     * @return
     */
    public Page<Application> paginateAdminList(Integer pageNumber, Integer pageSize, String keywords, Integer type, Boolean enable) {
        if (notOk(keywords) && notOk(type) && enable == null) {
            return paginate("id", "desc", pageNumber, pageSize);
        }
        Okv otherParas = Okv.create();
        if (isOk(type)) {
            otherParas.set("type", type);
        }
        otherParas.setIfNotNull("enable", enable);

        if (notOk(keywords)) {
            return paginate(otherParas, "id", "desc", pageNumber, pageSize);
        }
        return paginateByKeywords("id", "desc", pageNumber, pageSize, keywords, "name,brief_info,app_id", otherParas);
    }

    /**
     * 变更AppSecret
     *
     * @param id
     * @return
     */
    public Ret changeAppSecret(Long id) {
        if (notOk(id)) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        Application application = findById(id);
        if (application == null) {
            return fail(JBoltMsg.DATA_NOT_EXIST);
        }
        application.setAppSecret(genAppSecret());
        boolean success = application.update();
        if (success) {
            //cache
            addUpdateSystemLog(application.getId(), JBoltUserKit.getUserId(), application.getName(), "的AppSecret");
        }
        return ret(success);
    }

    /**
     * 获取关联对象
     *
     * @param type
     * @param linkTargetId
     * @return
     */
    public Object getLinkTarget(Integer type, Long linkTargetId) {
        if (notOk(type) || notOk(linkTargetId)) {
            return null;
        }
        JBoltApplicationType typeEnum = JBoltEnum.getEnumObjectByValue(JBoltApplicationType.class, type);
        Object jBoltAppLinkTarget = null;


        try {
            switch (typeEnum) {
                case WECHAT_XCX:
                case MP_H5:
                    jBoltAppLinkTarget = JBoltMethodCaller.call(
                            "cn.jbolt.wechat.service.JBoltWechatMpinfoService",
                            "getAppLinkTargetInfo",
                            new Class[]{Long.class}, new Object[]{linkTargetId}
                    );
//                jBoltAppLinkTarget = wechatMpinfoService.getAppLinkTargetInfo(linkTargetId);
                    break;
                case ALIPAY_XCX:
                    break;
                case BAIDU_XCX:
                    break;
                case DOUYIN_XCX:
                    break;
                case MOBILE_APP:
                    break;
                case MOBILE_H5:
                    break;
                case OTHER:
                    break;
                case PC_DESKTOP:
                    break;
                case PC_WEB:
                    break;
                case QQ_XCX:
                    break;
                case TOUTIAO_XCX:
                    break;
                default:
                    break;
            }
            return jBoltAppLinkTarget;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 清除关联对象 特殊情况使用 就是他关联的对象找不到了才会出
     *
     * @param id
     * @return
     */
    public Ret removeLinkTarget(Long id) {
        Application application = findById(id);
        if (application == null) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        Long linkTargetId = application.getLinkTargetId();
        if (notOk(linkTargetId)) {
            return fail("应用尚未关联任何对象");
        }
        application.setLinkTargetId(null);
        boolean success = application.update();
        if (success) {
            addUpdateSystemLog(id, JBoltUserKit.getUserId(), application.getName(), "，解除了关联的" + application.getTypeName() + "[id:" + linkTargetId + "]");
        }
        return ret(success);
    }


    /**
     * 保存
     *
     * @param app
     * @return
     */
    public Ret save(Application app) {
        if (app == null || isOk(app.getId()) || notOk(app.getName()) || notOk(app.getType())) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        String name = app.getName().trim();
        if (existsName(name)) {
            return fail(JBoltMsg.DATA_SAME_NAME_EXIST);
        }
        app.setName(name);
        Date now = new Date();
        app.setCreateTime(now);
        app.setUserId(JBoltUserKit.getUserId());
        app.setUpdateTime(now);
        app.setUpdateUserId(JBoltUserKit.getUserId());
        app.setEnable(false);
        app.setAppId(genAppId());
        app.setAppSecret(genAppSecret());
        if (app.getNeedCheckSign() == null) {
            app.setNeedCheckSign(true);
        }
        boolean success = app.save();
        if (success) {
            //添加日志
            addSaveSystemLog(app.getId(), JBoltUserKit.getUserId(), app.getName());
        }
        return ret(success);
    }


    /**
     * 更新
     *
     * @param app
     * @return
     */
    public Ret update(Application app) {
        if (app == null || notOk(app.getId()) || notOk(app.getName()) || notOk(app.getType())) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        String name = app.getName().trim();
        if (existsName(name, app.getId())) {
            return fail(JBoltMsg.DATA_SAME_NAME_EXIST);
        }
        app.setName(name);
        app.setUpdateUserId(JBoltUserKit.getUserId());
        boolean success = app.update();
        if (success) {
            //添加日志
            addUpdateSystemLog(app.getId(), JBoltUserKit.getUserId(), app.getName());
        }
        return ret(success);
    }

    /**
     * 得到API上专用的数据 去掉一些无用数据
     *
     * @param appId
     * @return
     */
    public Application getApiApplicationByAppId(String appId) {
        Application application = getByAppId(appId);
        if (application == null) {
            return null;
        }
        application.removeNullValueAttrs();
        application.remove("brief_info", "create_time", "update_time", "user_id", "update_user_id");
        return application;
    }

    /**
     * 通过AppId获取一个application
     *
     * @param appId
     * @return
     */
    public Application getByAppId(String appId) {
        return findFirst(Okv.by("app_id", appId));
    }

    /**
     * 检测是否存在 不存在就初始化 系统内置平台自身application
     */
    public Application checkAndInitInnerPlatformApplication() {
        Application application = findFirst(selectSql().eq("type", JBoltApplicationType.INNER_PLATFORM.getValue()));
        if (application == null) {
            User user = jboltUserService.getOneSystemAdmin();
            application = new Application();
            if (user != null) {
                application.setUserId(user.getId());
                application.setUpdateUserId(user.getId());
            }
            application.setEnable(true);
            application.setBriefInfo("开发平台内置应用");
            application.setType(JBoltApplicationType.INNER_PLATFORM.getValue());
            application.setIsInner(true);
            application.setNeedCheckSign(false);
            application.setName("内置_平台自身");
            application.setAppId(genAppId());
            application.setAppSecret(genAppSecret());
            application.setCreateTime(new Date());
            application.setUpdateTime(application.getCreateTime());
            boolean success = application.save();
            if (!success) {
                throw new RuntimeException("checkAndInitInnerPlatformApplication save 失败");
            }
            //添加日志
            addSaveSystemLog(application.getId(), JBoltUserKit.getUserId(), application.getName());
        }
        return application;
    }

    /**
     * 生成32位appSecret
     *
     * @return
     */
    public String genAppSecret() {
        return Base64Kit.encode(JBoltRandomUtil.randomLowWithNumber(32));
    }

    /**
     * 生成一个appId
     *
     * @return
     */
    public String genAppId() {
        String appId = "jb" + JBoltRandomUtil.randomLowWithNumber(10) + "olt";
        if (exists("app_id", appId)) {
            return genAppId();
        }
        return appId;
    }

    @Override
    protected int systemLogTargetType() {
        return JBoltSystemLogTargetType.APPLICATION.getValue();
    }

    @Override
    public String checkCanDelete(Application application, Kv kv) {
        if (application.getIsInner() != null && application.getIsInner()) {
            return "内置应用，不可删除";
        }
        return checkInUse(application, kv);
    }

    @Override
    public String checkInUse(Application application, Kv kv) {
        if (isOk(application.getLinkTargetId())) {
            return "此应用已被其它数据绑定使用，不能删除";
        }
        return null;
    }

    @Override
    protected String afterDelete(Application application, Kv kv) {
        //TODO 删除统计信息
        //TODO 关联信息等
        processLinkTarget(application.getLinkTargetId(), application.getType());
        addDeleteSystemLog(application.getId(), JBoltUserKit.getUserId(), application.getName());
        return null;
    }

    /**
     * 删除关联数据
     *
     * @param linkTargetId
     * @param type
     */
    private void processLinkTarget(Long linkTargetId, Integer type) {
        JBoltApplicationType et = JBoltEnum.getEnumObjectByValue(JBoltApplicationType.class, type);
        if (et == null) {
            return;
        }
        try {
            switch (et) {
                case WECHAT_XCX:
                case MP_H5:
                    JBoltMethodCaller.call(
                            "cn.jbolt.wechat.service.JBoltWechatMpinfoService",
                            "removeLinkApp",
                            new Class[]{Long.class}, new Object[]{linkTargetId}
                    );
                    //wechatMpinfoService.removeLinkApp(linkTargetId);
                    break;
                case ALIPAY_XCX:
                    //TODO 待实现
                    break;
                case BAIDU_XCX:
                    //TODO 待实现
                    break;
                case DOUYIN_XCX:
                    //TODO 待实现
                    break;
                case MOBILE_APP:
                    //TODO 待实现
                    break;
                case MOBILE_H5:
                    //TODO 待实现
                    break;
                case PC_DESKTOP:
                    //TODO 待实现
                    break;
                case PC_WEB:
                    //TODO 待实现
                    break;
                case QQ_XCX:
                    //TODO 待实现
                    break;
                case TOUTIAO_XCX:
                    //TODO 待实现
                    break;
                case OTHER:
                    //TODO 待实现
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    public String checkCanToggle(Application app, String column, Kv kv) {
        if (app.getIsInner() != null && app.getIsInner()) {
            return "内置应用，不可操作";
        }
        return null;
    }


}
